package cn.risebd.utils;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.codec.binary.Base64;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;

/**
 * @category 二维码工具类，生成二维码需要依赖zxing包
 * @author yiz
 * @date 2016年5月13日 上午8:46:28
 * @version 1.0.0 
 * @copyright pycredit.cn
 */
public class QRCodeUtil {

	private static final int BLACK = 0xff000000;
	private static final int WHITE = 0xFFFFFFFF;

	/**
	 * 生成二维码
	 * 
	 * @param matrix
	 * @return
	 */
	public static BufferedImage toBufferedImage(BitMatrix matrix) {
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		// 创建一张bitmap图片，采用图片效果TYPE_INT_ARGB
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				image.setRGB(x, y, matrix.get(x, y) == true ? BLACK : WHITE);
			}
		}
		return image;
	}

	/**
	 * 将生成的二维码图片转化为base64编码，直接传给浏览器显示 好处是可以传图片的同时将参数也一并传递过去
	 * 
	 * @param content
	 * @param width
	 * @param height
	 * @return
	 */
	public static String toBase64(String content, int width, int height) {
		String qrCodeBASE64 = null;
		try {
			// 加密
			Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
			hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
			BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
			bitMatrix = deleteWhite(bitMatrix, 10);
			BufferedImage bufferedImage = QRCodeUtil.toBufferedImage(bitMatrix);
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
			byte[] data = byteArrayOutputStream.toByteArray();
			byteArrayOutputStream.flush();
			byteArrayOutputStream.close();
			//使用common的Base64工具类
			qrCodeBASE64 = Base64.encodeBase64String(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return qrCodeBASE64;
	}

	/**
	 * @category 生成二维码二进制流
	 * @throws WriterException
	 * @throws IOException
	 */
	public static byte[] createQr(String content, int width, int height) throws Exception {
		// 加密
		Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵
		bitMatrix = deleteWhite(bitMatrix, 10);
		ByteArrayOutputStream swapStream = null;
		byte[] data = null;
		try {
			swapStream = new ByteArrayOutputStream();
			MatrixToImageWriter.writeToStream(bitMatrix, "png", swapStream);
			// 得到二进制流
			data = swapStream.toByteArray();
			return data;
		} catch (Exception e) {
			throw e;
		} finally {
			if (null != swapStream) {
				try {
					swapStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 生成二维码以流的形式存在
	 * 
	 * @param matrix
	 * @param format
	 * @param out
	 * @throws IOException
	 */
	public static void writeToFile(BitMatrix matrix, String format, OutputStream out) throws IOException {
		BufferedImage image = toBufferedImage(matrix);
		ImageIO.write(image, format, out);
	}

	/**
	 * 生成的二维码以文件的形式存在
	 * 
	 * @param matrix
	 * @param format
	 * @param file
	 * @throws IOException
	 */
	public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
		BufferedImage image = toBufferedImage(matrix);
		ImageIO.write(image, format, file);
	}

	/**
	 * @category 去除白邊
	 * @param matrix
	 * @param margin
	 * @return
	 */
	public static BitMatrix deleteWhite(BitMatrix matrix, int margin) {
		int tempM = margin * 2;
		int[] rec = matrix.getEnclosingRectangle(); // 获取二维码图案的属性
		int resWidth = rec[2] + tempM;
		int resHeight = rec[3] + tempM;
		BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); // 按照自定义边框生成新的BitMatrix
		resMatrix.clear();
		for (int i = margin; i < resWidth - margin; i++) { // 循环，将二维码图案绘制到新的bitMatrix中
			for (int j = margin; j < resHeight - margin; j++) {
				if (matrix.get(i - margin + rec[0], j - margin + rec[1])) {
					resMatrix.set(i, j);
				}
			}
		}
		return resMatrix;
	}

}
